springboot整合minio8实现文件存储服务(最新版)

您所在的位置:网站首页 oss browser 能保存中文吗 springboot整合minio8实现文件存储服务(最新版)

springboot整合minio8实现文件存储服务(最新版)

2023-03-26 05:57| 来源: 网络整理| 查看: 265

近期在构建公司技术服务平台,在搭建完一些基础技术服务之后,考虑到项目过程中使用到很多文件存储功能,所以在平台上面提供统一的文件存储服务。

一开始计划直接使用阿里云OSS服务(想法简单了),后来与CTO讨论后,决定使用MinIO来完成该服务。然后开始学习MinIO相关知识,各种查看中英文版文档,现在最新的中文文档版本还是MinIO7的,所以查看了官网的英文版文档: MinIO文档

梳理下过程,将基础功能整理如下:

1. MinIO安装(docker单机)

前提需要了解docker及docker-compose相关知识。 windows本地使用MinIO,安装完docker及docker-compose后, 打开PowerShell,执行命令:

docker run -p 9000:9000 --name minio1 -v D:\data:/data -e "MINIO_ROOT_USER=phli" -e "MINIO_ROOT_PASSWORD=123456" minio/minio server /data

docker相关指令自行学习,本篇不做展开,将容器端口与宿主机端口做映射,文件存储目录挂载到本地D:\data目录下(容器内在/data下),设置MinIO root的user及password,minio/minio镜像。

本地MinIO启动成功,端口为9000。

2. 国际惯例,添加依赖

io.minio minio 8.0.3 复制代码

3. application配置

在这里插入图片描述 endpoint为本地MinIO服务url,accessKey及secretKey为MinIO设置的类似于userName/password。

4. MinIO配置类

@Data @Component public class MinIoClientConfig { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; /** * 注入minio 客户端 * @return */ @Bean public MinioClient minioClient(){ return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } } 复制代码

通过@Bean注入minIO客户端。

5. MinIOUtil类,完成与MinIO的操作

@Component public class MinIoUtil { @Autowired private MinioClient minioClient; /** * 查看存储bucket是否存在 * @param bucketName 存储bucket * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 创建存储bucket * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 删除存储bucket * @param bucketName 存储bucket名称 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 文件上传 * @param file 文件 * @param bucketName 存储bucket * @return Boolean */ public Boolean upload(MultipartFile file, String bucketName) { try { PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(file.getOriginalFilename()) .stream(file.getInputStream(),file.getSize(),-1).contentType(file.getContentType()).build(); //文件名称相同会覆盖 minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 文件下载 * @param bucketName 存储bucket名称 * @param fileName 文件名称 * @param res response * @return Boolean */ public void download(String bucketName, String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName) .object(fileName).build(); try (GetObjectResponse response = minioClient.getObject(objectArgs)){ byte[] buf = new byte[1024]; int len; try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){ while ((len=response.read(buf))!=-1){ os.write(buf,0,len); } os.flush(); byte[] bytes = os.toByteArray(); res.setCharacterEncoding("utf-8"); //设置强制下载不打开 res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()){ stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } /** * 查看文件对象 * @param bucketName 存储bucket名称 * @return 存储bucket内文件对象信息 */ public List listObjects(String bucketName) { Iterable results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); List objectItems = new ArrayList(); try { for (Result result : results) { Item item = result.get(); ObjectItem objectItem = new ObjectItem(); objectItem.setObjectName(item.objectName()); objectItem.setSize(item.size()); objectItems.add(objectItem); } } catch (Exception e) { e.printStackTrace(); return null; } return objectItems; } /** * 批量删除文件对象 * @param bucketName 存储bucket名称 * @param objects 对象名称集合 */ public Iterable removeObjects(String bucketName, List objects) { List dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); Iterable results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); return results; } } 复制代码

MinIoUtil提供了创建存储bucket、删除存储bucket、判断存储bucket是否存在、文件的上传下载、查看bucket内文件对象、批量删除文件对象等功能(存储bucket及文件对象等的概念不做赘述,可查看minIO官方文档)。

6. Controller类

这儿不做赘述,自行编写即可。仅以文件上传为demo:

@ApiOperation(value = "文件上传") @PostMapping("/upload") public Result upload(MultipartFile file, @RequestParam(value = "bucketName") String bucketName) { if (StringUtils.isBlank(bucketName)) { log.error("存储bucket名称为空,无法上传"); return Result.fail("存储bucket名称为空,无法上传"); } if (!minIoUtil.upload(file, bucketName)) { log.error("文件上传异常"); return Result.fail("文件上传异常"); } return Result.success("文件上传成功"); } 复制代码

然后就可以调用接口完成文件上传了,可以发现在本地及容器内均有所上传的文件。

补充说明:

MinIO在正式环境往往是分布式,分布式Minio可以让你将多块硬盘(甚至在不同的机器上)组成一个对象存储服务。由于硬盘分布在不同的节点上,分布式Minio避免了单点故障。

Docker Compose允许定义和运行单主机,多容器Docker应用程序。使用Compose,您可以使用Compose文件来配置MinIO服务。 然后,使用单个命令,您可以通过你的配置创建并启动所有分布式MinIO实例。 分布式MinIO实例将部署在同一主机上的多个容器中。 这是建立基于分布式MinIO的开发,测试和分期环境的好方法。

Docker Compose定义运行单主机,复杂场景可以考虑Kubernetes或者Docker Swarm,具体配置可查看MinIO官网文档。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3